""" Common sound package """
import math
import os
import itertools
import traceback
from S3D.Util import Workspace
from S3D import PS, IO
from S3D.Algorithms import matchBySimpleWildcard

MIN_DB          = -64

SHOW_PLATFORMS  = ["PC",    "Xbox360",      "PS3"]
SOUND_PLATFORMS = ["pc",    "xbox360",      "ps3"]
PS_PLATFORMS    = ["PC",    "X360",         "PS3"]
FMOD_PLATFORMS  = ["_PC_",  "_XBOX360_",    "_PS3_"]

def DbToVolume(db):
    return math.pow(10, db / 20.0)

MIN_VOLUME      = DbToVolume(MIN_DB)

def VolumeToDb(volume):
    if volume < MIN_VOLUME:
        return MIN_DB
    return 20 * math.log10(volume)

EVENT_PROPERTIES_IN_DB = 0, 1, 2

EVENT_PROPERTIES = [
    ("Volume",              "volume_db"),
    ("Reverb Wet Level",    "reverblevel_db"),
    ("Reverb Dry Level",    "reverbdrylevel_db"),
    ("Min Distance",        "mindistance"),
    ("Max Distance",        "maxdistance"),
    ("2D Speaker L",        "speaker_l"),
    ("2D Speaker R",        "speaker_r"),
    ("2D Speaker C",        "speaker_c"),
    ("2D Speaker LR",       "speaker_lb"),
    ("2D Speaker RR",       "speaker_rb"),
    ("Speaker LFE",         "speaker_lfe"),
]

def getSourcePath():
    return Workspace.getRecordWs("sound_src_dir")

def getPrebuildPath():
    return Workspace.getRecordWs("sound_bin_dir")

def getSoundConfigPath():
    ps_dir = Workspace.getRecordWs("ps_dir")

    for ps in ps_dir.split(';'):
        src = os.path.join(ps, "sound_config.ps")
        if not os.path.exists(src):
            continue

        return src

    raise IOError("sound_config.ps not found")

def getProjectsList():
    try:
        config = PS.parseFile(getSoundConfigPath())
        res = itertools.chain(config.projects, config.localized_projects)
        return ["%s.fdp" % p for p in res]
    except (IOError, PS.ParserError, PS.TokenizerError):
        return []

def getProjectsPathList():
    sourcePath = getSourcePath()
    return [os.path.join(sourcePath, p) for p in getProjectsList()]

def getLsaPath():
    return Workspace.getRecordWs("lsa_dir")

def getLevelsList():
    try:
        res = []

        lsaPath = getLsaPath()
        for path in IO.walk(lsaPath, ".lsa", False):
            levelName = IO.getName(path)

            try:
                lsa = PS.parseFile(path)

                found = False
                for platform in PS_PLATFORMS:
                    try:
                        found = lsa[platform].Sounds
                        break
                    except KeyError:
                        pass

                if found:
                    res.append(levelName)
            except (PS.ParserError, PS.TokenizerError):
                traceback.print_exc()

        return res

    except (IOError, PS.ParserError, PS.TokenizerError):
        return []

def getLevelsStats():
    """ returns map {level <-> {sounds}} """
    res = {}

    lsaPath = getLsaPath()
    for path in IO.walk(lsaPath, ".lsa", False):
        print(path)
        levelName = IO.getName(path)
        sounds = set()

        try:
            lsa = PS.parseFile(path)

            for platform in PS_PLATFORMS:
                try:
                    sounds.update(lsa[platform].Sounds)
                except KeyError:
                    pass
        except (PS.ParserError, PS.TokenizerError):
            traceback.print_exc()

        if sounds:
            res[levelName] = sounds

    return res

class _AutoloadingBanksInfo:
    def __init__(self, config):
        self.lists      = []
        self.wildcards  = []
        for index, platform in enumerate(PS_PLATFORMS):
            curSet = set()
            curWildcards = []
            self.lists.append(curSet)
            self.wildcards.append(curWildcards)

            for bank in config[platform].autoloadBanks:
                if '*' not in bank:
                    curSet.add(bank)
                else:
                    wildcard = []
                    if bank.startswith('*'):
                        wildcard.append('')

                    wildcard.extend(bank.replace('*', ' ').split())
                    curWildcards.append(wildcard)

    def isAutoload(self, platformIndex, name):
        if name in self.lists[platformIndex]:
            return True

        for p in self.wildcards[platformIndex]:
            if matchBySimpleWildcard(name, p, True):
                return True

        return False

def getAutoloadingBanksInfo():
    soundsConfigPath = getSoundConfigPath()
    config = PS.parseFile(soundsConfigPath)

    return _AutoloadingBanksInfo(config)